package jdk8.streamsapi;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import jdk8.streamsapi.enums.Status;

/**
 * Description: jdk1.8新特性：Streams
 * 新增的Stream API（java.util.stream）将生成环境的函数式编程引入了Java库中。
 * 这是目前为止最大的一次对Java库的完善，以便开发者能够写出更加有效、更加简洁和紧凑的代码。
 * Steam API极大得简化了集合操作。
 * 
 * 个人认为：很有用呀，在处理集合这一方面很有用
 * @author Kwum
 * @date 2017年6月28日 下午3:26:02
 * @version 1.0
 */

public class Run {
    
    private static Collection<Task> tasks = Arrays.asList(
        new Task( Status.OPEN, 5 ),
        new Task( Status.OPEN, 13 ),
        new Task( Status.CLOSED, 8 ) 
    );

    public static void main(String[] args) throws IOException {
        //一：在这个task集合中一共有多少个OPEN状态的点？
        //在Java 8之前，要解决这个问题，则需要使用foreach循环遍历task集合；
        //但是在Java 8中可以利用steams解决：包括一系列元素的列表，并且支持顺序和并行处理。
        // Calculate total points of all active tasks using sum()
        long totalPointsOfOpenTasks = tasks
            .stream()   //tasks集合被转换成steam表示
            .filter( task -> task.getState() == Status.OPEN )   //在steam上的filter操作会过滤掉所有CLOSED的task
            .mapToInt( Task::getPoint )    //mapToInt操作基于每个task实例的Task::getPoints方法将task流转换成Integer集合
            .sum();    //通过sum方法计算总和
        System.out.println( "Total points: " + totalPointsOfOpenTasks );
        
        //steam的另一个价值是创造性地支持并行处理（parallel processing）。对于上述的tasks集合，我们可以用下面的代码计算所有任务的点数之和
        // Calculate total points of all tasks
        double totalPoints = tasks
           .stream()
           .parallel()  //使用parallel方法并行处理所有的task
           .map( task -> task.getPoint() ) // or map( Task::getPoints ) 
           .reduce( 0, Integer::sum );  //reduce方法计算最终的结果
        System.out.println( "Total points (all tasks): " + totalPoints );
        
        //对于一个集合，经常需要根据某些条件对其中的元素分组。
        // Group tasks by their status
        Map< Status, List< Task > > map = tasks
            .stream()
            .collect( Collectors.groupingBy( Task::getState ) );
        System.out.println( map );
        
        //计算所占比重
        // Calculate the weight of each tasks (as percent of total points) 
        final Collection< String > result = tasks
            .stream()                                        // Stream< String >
            .mapToInt( Task::getPoint )                     // IntStream
            .asLongStream()                                  // LongStream
            .mapToDouble( points -> points / totalPoints )   // DoubleStream
            .boxed()                                         // Stream< Double >
            .mapToLong( weigth -> ( long )( weigth * 100 ) ) // LongStream
            .mapToObj( percentage -> percentage + "%" )      // Stream< String> 
            .collect( Collectors.toList() );                 // List< String > 
        System.out.println( result );
        
        //读取文件
        Path path = new File( "derby.log" ).toPath();
        try( Stream< String > lines = Files.lines( path, StandardCharsets.UTF_8 ) ) {
            lines.onClose( () -> System.out.println("Done!") ).forEach( System.out::println );
        }
    }
}
